﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace comm.objst
{
    #region NValueViewType
    [Serializable]
    public enum NValueBehaviorType
    {
        HERO_OTHRE_PLAYER_VIEW = 1
    }
    #endregion

    #region NValueGroup
    [Serializable]
    public enum NValueGroup
    {
        ALL = 0,
        HERO = 1,
        UNIT = 2,
        MONSTER = 3
    }
    #endregion

    #region NValueType
    [Serializable]
    public enum NValueType
    {
        UNSIGNED = 0,
        SIGNED = 1,
        ZERO_OR_ONE = 2
    }
    #endregion

    #region NValueSymbol
    [Serializable]
    public enum NValueSymbol
    {
        PLUS = 0,
        PLUSX = 1,
        MINUS = 2,
        MINUSX = 3,
        EQUAL = 4,
        EQUALX = 5
    }
    #endregion

    #region NValueComputing
    [Serializable]
    public class NValueComputing
    {
        static string[] _symbols = new string[] { "+", "+*", "-", "-*", "=", "=*" };
        public static string[] GetSymbols()
        {
            return (string[])_symbols.Clone();
        }
        public static NValueComputing Parse(string expr)
        {
            for (int i = 0, len = _symbols.Length; i < len; i++)
            {
                var symbol = _symbols[i];
                if (expr.IndexOf(symbol) == 0 && expr.Length > symbol.Length)
                {
                    var d = 0d;
                    if (double.TryParse(expr.Remove(0, symbol.Length), out d) && d > 0)
                    {
                        return new NValueComputing { Symbol = (NValueSymbol)i, Value = d };
                    }
                }
            }
            return null;
        }

        string _name = null;
        public string Name
        {
            get
            {
                if (_name == null)
                {
                    _name = "";
                }
                return _name;
            }
            set { _name = value; }
        }

        public NValueSymbol Symbol { get; set; }
        public double Value { get; set; }

        public override string ToString()
        {
            return _name + " : " + Symbol + " " + Value;
        }
    }
    #endregion

    #region NValue
    [Serializable]
    public class NValue
    {
        static Dictionary<NValueType, Func<long, long>> _funcDic = new Dictionary<NValueType, Func<long, long>>();
        static Dictionary<NValueSymbol, Func<double, long, long>> _calcDic = new Dictionary<NValueSymbol, Func<double, long, long>>();
        static NValue()
        {
            _funcDic.Add(NValueType.UNSIGNED, v => { return Math.Max(0, v); });
            _funcDic.Add(NValueType.SIGNED, v => { return v; });
            _funcDic.Add(NValueType.ZERO_OR_ONE, v => { return Math.Min(1, Math.Max(0, v)); });

            _calcDic.Add(NValueSymbol.PLUS, (d, v) => { return (long)Math.Floor(d + v); });
            _calcDic.Add(NValueSymbol.PLUSX, (d, v) => { return (long)Math.Floor(d + d * v); });
            _calcDic.Add(NValueSymbol.MINUS, (d, v) => { return (long)Math.Floor(v - d); });
            _calcDic.Add(NValueSymbol.MINUSX, (d, v) => { return (long)Math.Floor(v - v * d); });
            _calcDic.Add(NValueSymbol.EQUAL, (d, v) => { return (long)Math.Floor(d); });
            _calcDic.Add(NValueSymbol.EQUALX, (d, v) => { return (long)Math.Floor(d * v); });
        }

        public static long Parse(NValueType type, long value)
        {
            return _funcDic[type](value);
        }

        long _value = 0;
        public long Value
        {
            get
            {
                return _value;
            }
            set
            {
                _value = Parse(NType, value);
            }
        }

        public NValueGroup Group { get; set; }
        public NValueType NType { get; set; }

        public void Calc(NValueComputing computing)
        {
            Value = _calcDic[computing.Symbol](computing.Value, Value);
        }
    }
    #endregion
}
